/*
 * Twanoh Library, a useful Android utility library.
 * Copyright (C) 2006 Richard Schilling
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package gnu.org.twanoh.app;

import java.util.Collections;
import java.util.SortedMap;
import android.app.AlertDialog;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * This is a custom dialogbox that displays a list of drawables to select from.
 * To use this class some views are required to be defined, and the constants
 * ID_IMAGEVIEW, and ID_TEXTVIEW must be defined.
 * 
 * @author Richard Schilling (coderroadie@gmail.com)
 */
public class DrawableSelectDialog extends AlertDialog {

    /**
     * A convenience constant to make it easy to identify where the identifiers
     * for the image view is set for each row in th list. This can be used to
     * retrieve the ImageView that displays the icon.
     * <p>
     * To use this, define a view with an imageview. Assign that imageview ID to
     * ID_IMAGEVIEW.
     */
    public static final int ID_IMAGEVIEW = Integer.MIN_VALUE;

    /**
     * A convenience constant to make it easy to identify where the identifiers
     * for the text view is set for each row in the list. This can be used to
     * retrieve the text view that displays the name.
     */
    public static final int ID_TEXTVIEW = Integer.MIN_VALUE;

    /**
     * The padding applied by default to each image view. This is passed to
     * ImageView.setPadding() for all four dimensions.
     */
    public static final int DEFAULT_IMAGEVIEW_PADDING = 10;

    /**
     * The table that all the items are retrieved from. The key is an the name
     * to display, and the value is drawable resource id.
     */
    private SortedMap<String, Integer> mMap;

    /**
     * The sorted list of keys.
     */
    public String[] mKeys;

    private final int viewResource;

    /**
     * The list view that displays all the items.
     */
    private GridView mItems;

    /**
     * Creates the dialog. The drawables passed is converted to an
     * UnmodifiableSortedMap.
     * 
     * @param context the parent context
     * @param cancelable if true the dialog can be cancelled.
     * @param cancelListener the callback to invoke if the dialog is cancelled.
     * @param drawables a mapping of names to show in the list with the resource
     *            identifiers (presumably R.drawable items).
     */
    public DrawableSelectDialog(Context context, boolean cancelable,
            OnCancelListener cancelListener, SortedMap<String, Integer> drawables, int viewResource) {
        super(context, cancelable, cancelListener);
        initialize(drawables);
        this.viewResource = viewResource;
    }

    /**
     * Creates the dialog.
     * 
     * @param drawables a mapping of names to show in the list with the resource
     *            identifiers (presumably R.drawable items).
     */
    public DrawableSelectDialog(Context context, int theme, SortedMap<String, Integer> drawables,
            int viewResource) {
        super(context, theme);
        initialize(drawables);
        this.viewResource = viewResource;

    }

    /**
     * Creates the dialog.
     * 
     * @param drawables a mapping of names to show in the list with the resource
     *            identifiers (presumably R.drawable items).
     */
    public DrawableSelectDialog(Context context, SortedMap<String, Integer> drawables,
            int viewResource) {
        super(context);
        initialize(drawables);
        this.viewResource = viewResource;

        if (ID_TEXTVIEW == Integer.MIN_VALUE || ID_IMAGEVIEW == Integer.MIN_VALUE)
            throw new IllegalStateException(
                    "the constants ID_TEXTVIEW and ID_IMAGEVIEW must be defined in order to use this class.");

    }

    private void initialize(SortedMap<String, Integer> drawables) {
        mMap = Collections.unmodifiableSortedMap(drawables);
        mKeys = mMap.keySet().toArray(new String[0]);

        // mItems = (GridView) inflater.inflate(R.layout.iconlayoutgrid, null);

        mItems = new GridView(getContext());
        mItems.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT,
                android.view.ViewGroup.LayoutParams.FILL_PARENT));
        mItems.setHorizontalSpacing(10);
        mItems.setVerticalSpacing(10);
        mItems.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        mItems.setNumColumns(GridView.AUTO_FIT);
        mItems.setGravity(Gravity.CENTER);

        mItems.setAdapter(new IconAdapter());

        super.setView(mItems);

    }

    /**
     * Sets the item click listener of the list that is displayed.
     * 
     * @param listener the listener to execute when an item in the list is
     *            clicked.
     */
    public final void setOnItemClickListener(OnItemClickListener listener) {
        mItems.setOnItemClickListener(listener);
    }

    /**
     * Sets the item long click listener of the list that is displayed.
     * 
     * @param listener the listener to execute when an item in the list is
     *            clicked.
     */
    public final void setOnItemLongClickListener(OnItemLongClickListener listener) {
        mItems.setOnItemLongClickListener(listener);
    }

    @Override
    public final void setView(View view, int viewSpacingLeft, int viewSpacingTop,
            int viewSpacingRight, int viewSpacingBottom) {

        throw new UnsupportedOperationException("The view of this alert dialog cannot be changed.");
    }

    @Override
    public final void setView(View view) {
        throw new UnsupportedOperationException("The view of this alert dialog cannot be changed.");
    }

    @Override
    public final void setContentView(int layoutResID) {
        throw new UnsupportedOperationException("The view of this alert dialog cannot be changed.");
    }

    @Override
    public final void setContentView(View view, android.view.ViewGroup.LayoutParams params) {
        throw new UnsupportedOperationException("The view of this alert dialog cannot be changed.");
    }

    @Override
    public void setContentView(View view) {
        throw new UnsupportedOperationException("The view of this alert dialog cannot be changed.");
    }

    /**
     * This callback is invoked whenever the view is retrieved for display in
     * the list. The view specified is the view that
     * is used to display each
     * row. By default it's a LinearLayout, but this may change in future
     * releases. The image view can be retrieved by calling
     * {@code currentView.findViewById(ID_IMAGEVIEW}, and the TextView that
     * displays the text can be retrieved by calling
     * {@code currentView.findViewById(ID_TEXTVIEW)}.
     * 
     * @param currentView
     */
    public void decorateRow(View currentView) {

    }

    private class IconAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mMap.size();
        }

        @Override
        public Object getItem(int position) {
            return mKeys[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            if (convertView == null) {

                LayoutInflater inflater = getLayoutInflater();
                LinearLayout lLayout = (LinearLayout) inflater.inflate(viewResource, parent, false);
                if (lLayout == null)
                    throw new IllegalArgumentException("resource id is not a valid view.");

                decorateRow(lLayout);

                convertView = lLayout;

            }

            ImageView iView = (ImageView) convertView.findViewById(ID_IMAGEVIEW);
            if (iView == null)
                throw new IllegalArgumentException(
                        "layout does not contain an image view with and ID of " + ID_IMAGEVIEW);
            iView.setImageResource(mMap.get(mKeys[position]));

            TextView tView = (TextView) convertView.findViewById(ID_TEXTVIEW);
            if (tView == null)
                throw new IllegalArgumentException(
                        "layout does not contain a text view with and ID of " + ID_TEXTVIEW);
            tView.setText(mKeys[position]);

            return convertView;

        }
    }

}
